/*
* Sun Public License Notice
*
* The contents of this file are subject to the Sun Public License
* Version 1.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://www.sun.com/
*
* The Original Code is Forte for Java, Community Edition. The Initial
* Developer of the Original Code is Sun Microsystems, Inc. Portions
* Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved.
*/
package org.netbeans.modules.form;
import org.openide.util.datatransfer.*;
import java.awt.*;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import javax.swing.*;
/**
*
* @author Ian Formanek
*/
public class RADMenuComponent extends RADMenuItemComponent implements ComponentContainer {
/** Hashtable, where keys are Integer(T_XXX), and values are Class[] - supported NewTypes
* for the different menu types
* @associates Class*/
static HashMap supportedNewMenu;
/** Init supportedNewMenu table. */
static {
supportedNewMenu = new HashMap();
supportedNewMenu.put(new Integer(T_MENUBAR), new Class[] { Menu.class });
supportedNewMenu.put(new Integer(T_MENU), new Class[] { MenuItem.class, CheckboxMenuItem.class, Menu.class });
supportedNewMenu.put(new Integer(T_POPUPMENU), new Class[] { MenuItem.class, CheckboxMenuItem.class, Menu.class });
supportedNewMenu.put(new Integer(T_JMENUBAR), new Class[] { JMenu.class });
supportedNewMenu.put(new Integer(T_JMENU), new Class[] { JMenuItem.class, JCheckBoxMenuItem.class, JRadioButtonMenuItem.class, JMenu.class });
supportedNewMenu.put(new Integer(T_JPOPUPMENU), new Class[] { JMenuItem.class, JCheckBoxMenuItem.class, JRadioButtonMenuItem.class, JMenu.class });
}
// -----------------------------------------------------------------------------
// Private variables
/**
* @associates RADComponent
*/
private ArrayList subComponents;
// -----------------------------------------------------------------------------
// Initialization
/** Support for new types that can be created in this node.
* @return array of new type operations that are allowed
*/
public NewType[] getNewTypes () {
Class[] classes = (Class []) supportedNewMenu.get(new Integer(getMenuItemType ()));
if (classes == null)
return RADComponent.NO_NEW_TYPES;
NewType separator = createSeparatorNewType();
NewType[] types = new NewType[classes.length + ((separator != null) ? 1 : 0)];
for (int i = 0; i < classes.length; i++) {
types[i] = new NewMenuType(classes[i]);
}
if (separator != null)
types[types.length - 1] = separator;
return types;
}
// -----------------------------------------------------------------------------
// SubComponents Management
public RADComponent[] getSubBeans () {
RADComponent[] components = new RADComponent [subComponents.size ()];
subComponents.toArray (components);
return components;
}
public void initSubComponents (RADComponent[] initComponents) {
subComponents = new ArrayList (initComponents.length);
for (int i = 0; i < initComponents.length; i++) {
subComponents.add (initComponents[i]);
((RADMenuItemComponent)initComponents[i]).initParent (this);
addVisualMenu ((RADMenuItemComponent)initComponents[i]);
}
}
public void reorderSubComponents (int[] perm) {
// XXX(-tdt) must make a copy of the component list, otherwise removing
// menu separator will break
// make a copy of item list
ArrayList list = new ArrayList(subComponents.size());
list.addAll(subComponents);
// shuffle the copy
for (int i = 0; i < perm.length; i++) {
int from = i;
int to = perm[i];
if (from == to) continue;
Object value = list.remove (from);
if (from < to) {
list.add (to - 1, value);
} else {
list.add (to, value);
}
}
// remove and re-add in new order
for (int i = 0, n = list.size(); i < n; i++)
remove((RADMenuItemComponent) list.get (i));
for (int i = 0, n = list.size(); i < n; i++)
add((RADMenuItemComponent) list.get (i));
getFormManager ().fireComponentsReordered (this);
}
public void add (RADComponent comp) {
if (!(comp instanceof RADMenuItemComponent)) throw new IllegalArgumentException ();
subComponents.add (comp);
((RADMenuItemComponent)comp).initParent (this);
addVisualMenu ((RADMenuItemComponent) comp);
((RADChildren)getNodeReference ().getChildren ()).updateKeys ();
}
public void remove (RADComponent comp) {
if (!(comp instanceof RADMenuItemComponent))
throw new IllegalArgumentException();
removeVisualMenu ((RADMenuItemComponent)comp);
subComponents.remove (comp);
((RADChildren)getNodeReference ().getChildren ()).updateKeys ();
}
public int getIndexOf (RADComponent comp) {
return subComponents.indexOf (comp);
}
/** Adds the menu represented by the node */
private void addVisualMenu (RADMenuItemComponent comp) {
Object o = getBeanInstance();
Object m = comp.getBeanInstance();
Object dto = getDesignTimeMenus (getFormManager ()).getDesignTime (o);
Object dtm = getDesignTimeMenus (getFormManager ()).getDesignTime (m);
switch (getMenuItemType ()) {
case T_MENUBAR:
((MenuBar)o).add((Menu)m);
((JMenuBar)dto).add ((JMenu) dtm);
((JMenuBar)dto).validate();
break;
case T_MENU:
if (comp.getMenuItemType () == T_SEPARATOR) {
((Menu)o).addSeparator();
((JMenu)dto).addSeparator();
} else {
((Menu)o).add((MenuItem)m);
((JMenu)dto).add((JMenuItem)dtm);
}
break;
case T_POPUPMENU:
if (comp.getMenuItemType () == T_SEPARATOR) {
((Menu)o).addSeparator();
((JMenu)dto).addSeparator();
} else {
((Menu)o).add((MenuItem)m);
((JPopupMenu)dto).add((JMenuItem)dtm);
}
break;
case T_JMENUBAR:
((JMenuBar)o).add((JMenu)m);
((JMenuBar)o).validate();
break;
case T_JMENU:
if (comp.getMenuItemType () == T_JSEPARATOR) {
((JMenu)o).addSeparator();
} else {
((JMenu)o).add((JMenuItem)m);
}
break;
case T_JPOPUPMENU:
if (comp.getMenuItemType () == T_JSEPARATOR) {
((JPopupMenu)o).addSeparator();
} else {
((JPopupMenu)o).add((JMenuItem)m);
}
break;
}
}
/** Removes the menu represented by the node */
private void removeVisualMenu (RADMenuItemComponent comp) {
Object o = getBeanInstance();
Object m = comp.getBeanInstance();
Object dto = getDesignTimeMenus (getFormManager ()).getDesignTime (o);
Object dtm = getDesignTimeMenus (getFormManager ()).getDesignTime (m);
switch (getMenuItemType ()) {
case T_MENUBAR:
((MenuBar)o).remove((Menu)m);
((JMenuBar)dto).remove((JMenu)dtm);
((JMenuBar)dto).validate();
break;
case T_MENU:
if (comp.getMenuItemType () == T_SEPARATOR) {
((Menu)o).remove (subComponents.indexOf(comp));
((JMenu)dto).remove (subComponents.indexOf(comp));
} else {
((Menu)o).remove((MenuItem)m);
((JMenu)dto).remove((JMenuItem)dtm);
}
break;
case T_POPUPMENU:
if (comp.getMenuItemType () == T_SEPARATOR) {
((Menu)o).remove (subComponents.indexOf(comp));
// PENDING - dont know how to get reference to JPopupMenu.Separator
// so it is not supported by getDesignTimeMenu () !!
//((JPopupMenu)dto).remove((JPopupMenu.Separator)dtm);
} else {
((Menu)o).remove((MenuItem)m);
((JPopupMenu)dto).remove((JMenuItem)dtm);
}
break;
case T_JMENUBAR:
((JMenuBar)o).remove((JMenu)m);
((JMenuBar)o).validate();
break;
case T_JMENU:
if (comp.getMenuItemType () == T_JSEPARATOR) {
((JMenu)o).remove (subComponents.indexOf(comp));
} else {
((JMenu)o).remove((JMenuItem)m);
}
break;
case T_JPOPUPMENU:
if (comp.getMenuItemType () == T_JSEPARATOR) {
//XXX(-tdt) ((JPopupMenu)o).remove((JPopupMenu.Separator)m);
((JPopupMenu)o).remove (subComponents.indexOf(comp));
} else {
((JPopupMenu)o).remove((JMenuItem)m);
}
break;
}
}
// -----------------------------------------------------------------------------
// Debug methods
// -----------------------------------------------------------------------------
// Innerclasses
/** @return NewType for creating separator or null if this node doesn't support it.
*/
private NewType createSeparatorNewType() {
int type = getMenuItemType ();
return ((type == T_MENU) || (type == T_POPUPMENU) ||
(type == T_JMENU) || (type == T_JPOPUPMENU)) ? new NewSeparatorType() : null;
}
/** NewType class for creating the separator */
private class NewSeparatorType extends NewType {
/** Help context for the creation action.
* @return the help context
*/
public org.openide.util.HelpCtx getHelpCtx() {
return new org.openide.util.HelpCtx(this.getClass());
}
/** Display name for the creation action. This should be
* presented as an item in a menu.
*
* @return the name of the action
*/
public String getName() {
return FormEditor.getFormBundle ().getString("CTL_separator");
}
/** Create the object.
* @exception IOException if something fails
*/
public void create () throws IOException {
RADMenuItemComponent newSeparatorComp = new RADMenuItemComponent ();
newSeparatorComp.initialize (getFormManager ());
if ((getMenuItemType () == T_MENU) || (getMenuItemType () == T_POPUPMENU)) {
newSeparatorComp.setComponent (org.netbeans.modules.form.Separator.class);
} else {
newSeparatorComp.setComponent (JSeparator.class);
}
getFormManager ().addNonVisualComponent (newSeparatorComp, RADMenuComponent.this);
//XXX(-tdt) addVisualMenu (newSeparatorComp);
getFormManager ().selectComponent (newSeparatorComp, false);
return;
}
}
/** NewType for creating sub-MenuItem. */
class NewMenuType extends NewType {
/** Class which represents the menu class for this NewType */
Class item;
/** Constructs new NewType for the given menu class */
public NewMenuType(Class item) {
this.item = item;
}
/** Display name for the creation action. This should be
* presented as an item in a menu.
*
* @return the name of the action
*/
public String getName() {
String s = item.getName();
if (FormEditor.getFormSettings ().getShortBeanNames()) {
int index = s.lastIndexOf('.');
if (index != -1)
return s.substring(index + 1);
}
return s;
}
/** Create the object.
* @exception IOException if something fails
*/
public void create () throws IOException {
RADMenuItemComponent newMenuComp;
if ((RADMenuItemComponent.recognizeType(item) & MASK_CONTAINER) == 0) {
newMenuComp = new RADMenuItemComponent();
}
else {
newMenuComp = new RADMenuComponent();
}
newMenuComp.initialize (RADMenuComponent.this.getFormManager());
newMenuComp.setComponent (item);
if (newMenuComp instanceof RADMenuComponent) {
((RADMenuComponent)newMenuComp).initSubComponents (new RADComponent[0]);
}
RADMenuComponent.this.getFormManager().addNonVisualComponent (newMenuComp, RADMenuComponent.this);
// for some components, we initialize their properties with some non-default values
// e.g. a label on buttons, checkboxes
FormEditor.defaultMenuInit (newMenuComp);
addVisualMenu (newMenuComp);
RADMenuComponent.this.getFormManager().selectComponent (newMenuComp, false);
}
}
}
/*
* Log
* 10 Gandalf 1.9 3/7/00 Tran Duc Trung FIX #5894: cannot
* reorder menu items if there is a separator among them
* 9 Gandalf 1.8 12/8/99 Pavel Buzek
* 8 Gandalf 1.7 12/2/99 Pavel Buzek AWT menu is displayed in
* form at design time (a swing equivalent is created for each awt menu
* and displyed instead)
* 7 Gandalf 1.6 10/23/99 Ian Formanek NO SEMANTIC CHANGE - Sun
* Microsystems Copyright in File Comment
* 6 Gandalf 1.5 10/9/99 Ian Formanek Fixed bug 4411 - Delete
* of a jMenuItem does not work. (No action is performed.)
* 5 Gandalf 1.4 9/6/99 Ian Formanek Correctly works with
* separators - fixes bug 3703 - When a new separator is created usng New
* > Separator in a menu, an exception is thrown.
* 4 Gandalf 1.3 7/14/99 Ian Formanek Fixed problem with
* appearance of loaded menus
* 3 Gandalf 1.2 7/9/99 Ian Formanek Menu editor improvements
* 2 Gandalf 1.1 7/5/99 Ian Formanek improved
* 1 Gandalf 1.0 7/3/99 Ian Formanek
* $
*/